﻿using System.ComponentModel;
using System.Drawing.Drawing2D;

namespace PPSMS.Controllers
{

    [DefaultEvent("Click")]
    public partial class DashBoard : UserControl
    {
        public DashBoard()
        {
            InitializeComponent();

            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.DoubleBuffer, true);
            this.SetStyle(ControlStyles.ResizeRedraw, true);
            this.SetStyle(ControlStyles.Selectable, true);
            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            this.SetStyle(ControlStyles.UserPaint, true);
        }
        Font _wordFont = new Font("微软雅黑", 10, FontStyle.Bold);
        [Browsable(true), Category("自定义属性"), Description("文字字体")]
        public Font WordFont
        {
            get
            {
                return _wordFont;
            }
            set
            {
                _wordFont = value;
                this.Invalidate();
            }
        }
        Color _wordColor = Color.Black;
        /// <summary>
        /// 文字颜色
        /// </summary>
        [Browsable(true), Category("自定义属性"), Description("文字颜色")]
        public Color WordColor
        {
            get
            {
                return _wordColor;
            }
            set
            {
                _wordColor = value;
                this.Invalidate();
            }
        }
        bool _isWordShow = true;
        /// <summary>
        /// 文字是否显示
        /// </summary>
        [Browsable(true), Category("自定义属性"), Description("文字是否显示")]
        public bool IsWordShow
        {
            get
            {
                return _isWordShow;
            }
            set
            {
                _isWordShow = value;
                this.Invalidate();
            }
        }
        string _wordFormat = "实际温度：{0}℃";
        /// <summary>
        /// 文字是否显示的格式，例如："实际温度：{0}℃"，{0}为实际值的占位符
        /// </summary>
        [Browsable(true), Category("自定义属性"), Description("文字是否显示的格式，例如：'实际温度：{0}℃'，{0}为实际值的占位符")]
        public string WordFormat
        {
            get
            {
                return _wordFormat;
            }
            set
            {
                _wordFormat = value;
                this.Invalidate();
            }
        }
        float _wordPositionFactor = 0.6f;
        /// <summary>
        /// 底部文字所在位置
        /// </summary>
        [Browsable(true), Category("自定义属性"), Description("底部文字所在位置")]
        public float WordPositionFactor
        {
            get
            {
                return _wordPositionFactor;
            }
            set
            {
                if (value < 0 || value > 1)
                {
                    _wordPositionFactor = 0.6f;
                }
                else
                {
                    _wordPositionFactor = value;
                }
                this.Invalidate();
            }
        }
        float _startValue = 0;
        /// <summary>
        /// 开始值
        /// </summary>
        [Browsable(true), Category("自定义属性"), Description("开始值")]
        public float StartValue
        {
            get
            {
                return _startValue;
            }
            set
            {
                _startValue = value;
                this.Invalidate();
            }
        }
        float _endValue = 160;
        /// <summary>
        /// 结束值
        /// </summary>
        [Browsable(true), Category("自定义属性"), Description("结束值")]
        public float EndValue
        {
            get
            {
                return _endValue;
            }
            set
            {
                _endValue = value;
                this.Invalidate();
            }
        }
        float _sweepRange = 240;
        /// <summary>
        /// 量程跨度，即从开始值到结束值所占用的角度
        /// </summary>
        [Browsable(true), Category("自定义属性"), Description("量程跨度，即从开始值到结束值所占用的角度")]
        public float SweepRange
        {
            get
            {
                return _sweepRange;
            }
            set
            {
                if (value < 0)
                {
                    _sweepRange = 240;
                }
                else
                {
                    _sweepRange = value;
                }
                this.Invalidate();
            }
        }
        int _largeMarkCount = 9;
        /// <summary>
        /// 刻度间隔值
        /// </summary>
        [Browsable(true), Category("自定义属性"), Description("刻度间隔值")]
        public int LargeMarkCount
        {
            get
            {
                return _largeMarkCount;
            }
            set
            {
                if (value < 0)
                {
                    _largeMarkCount = 9;
                }
                else
                {
                    _largeMarkCount = value;
                }
                this.Invalidate();
            }
        }
        MarkType _markStyle = MarkType.Average;
        /// <summary>
        /// 刻度分配样式，是平均分配还是自定义刻度值分配
        /// </summary>
        [Browsable(true), Category("自定义属性"), Description(" 刻度分配样式，是平均分配还是自定义刻度值分配")]
        public MarkType MarkStyle
        {
            get
            {
                return _markStyle;
            }
            set
            {
                _largeMarkCount = 9;
                _markStyle = value;
                this.Invalidate();
            }
        }
        float[] _customMarkValue = { 0, 20, 40, 60, 80, 100, 120, 140, 160 };
        /// <summary>
        /// 自定义刻度值
        /// </summary>
        [Browsable(true), Category("自定义属性"), Description("自定义刻度值")]
        public float[] CustomMarkValue
        {
            get
            {
                return _customMarkValue;
            }
            set
            {
                _customMarkValue = value;
                this.Invalidate();
            }
        }
        Color _firstColor = Color.DodgerBlue;
        /// <summary>
        /// 第一部分颜色
        /// </summary>
        [Browsable(true), Category("自定义属性"), Description("第一部分颜色")]
        public Color FirstColor
        {
            get
            {
                return _firstColor;
            }
            set
            {
                _firstColor = value;
                this.Invalidate();
            }
        }
        int _firstColorHaveMarkCount = 6;
        /// <summary>
        /// 第一部分颜色所拥有的刻度数量
        /// </summary>
        [Browsable(true), Category("自定义属性"), Description("第一部分颜色所拥有的刻度数量")]
        public int FirstColorHaveMarkCount
        {
            get
            {
                return _firstColorHaveMarkCount;
            }
            set
            {
                if (value < 0)
                {
                    _firstColorHaveMarkCount = 2;
                }
                else
                {
                    _firstColorHaveMarkCount = value;
                }
                this.Invalidate();
            }
        }
        Color _secondColor = Color.LightGray;
        /// <summary>
        /// 第2部分颜色
        /// </summary>
        [Browsable(true), Category("自定义属性"), Description("第2部分颜色")]
        public Color SecondColor
        {
            get
            {
                return _secondColor;
            }
            set
            {
                _secondColor = value;
                this.Invalidate();
            }
        }
        int _outCircleWidth = 3;
        /// <summary>
        /// 外圆宽度
        /// </summary>
        [Browsable(true), Category("自定义属性"), Description("外圆宽度")]
        public int OutCircleWidth
        {
            get
            {
                return _outCircleWidth;
            }
            set
            {
                if (value < 0)
                {
                    return;
                }
                else
                {
                    _outCircleWidth = value;
                }
                this.Invalidate();
            }
        }
        float _pointerPartFactor = 0.1f;
        /// <summary>
        /// 指针部分所占的比例
        /// </summary>
        [Browsable(true), Category("自定义属性"), Description("指针部分所占的比例")]
        public float PointerPartFactor
        {
            get
            {
                return _pointerPartFactor;
            }
            set
            {
                if (value < 0 || value > 1)
                {
                    _pointerPartFactor = 0.2f;
                }
                else
                {
                    _pointerPartFactor = value;
                }
                this.Invalidate();
            }
        }
        /// <summary>
        /// 尺寸
        /// </summary>
        int Dimensions
        {
            get
            {
                if (Width < Height)
                {
                    return Width;
                }
                return Height;
            }
        }
        int _outCap = 5;
        /// <summary>
        /// 外间隙
        /// </summary>
        [Browsable(true), Category("自定义属性"), Description("外间隙")]
        public int OutGap
        {
            get
            {
                return _outCap;
            }
            set
            {
                if (value < 0)
                {
                    return;
                }
                _outCap = value;
                this.Invalidate();
            }
        }
        int _innerCap = 15;
        /// <summary>
        /// 内间隙
        /// </summary>
        [Browsable(true), Category("自定义属性"), Description("内间隙")]
        public int InnerGap
        {
            get
            {
                return _innerCap;
            }
            set
            {
                if (value < 0)
                {
                    return;
                }
                _innerCap = value;
                this.Invalidate();
            }
        }
        float _actualValue = 60;
        /// <summary>
        /// 实际值
        /// </summary>
        [Browsable(true), Category("自定义属性"), Description("实际值")]
        public float ActualValue
        {
            get
            {
                return _actualValue;
            }
            set
            {
                _actualValue = value;
                this.Invalidate();
            }
        }
        Color _markWordColor = Color.Black;
        [Browsable(true), Category("自定义属性"), Description("刻度文字颜色")]
        public Color MarkWordColor
        {
            get
            {
                return _markWordColor;
            }
            set
            {
                _markWordColor = value;
            }
        }
        Font _markWordFont = DefaultFont;
        [Browsable(true), Category("自定义属性"), Description("刻度文字字体")]
        public Font MarkWordFont
        {
            get
            {
                return _markWordFont;
            }
            set
            {
                _markWordFont = value;
                this.Invalidate();
            }
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            Graphics g = e.Graphics;
            //计算需要绘制的刻度数量
            g.SmoothingMode = SmoothingMode.AntiAlias; //使绘图质量最高，即消除锯齿
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.CompositingQuality = CompositingQuality.HighQuality;
            Dictionary<int, float> dic = new Dictionary<int, float>();
            if (MarkStyle == MarkType.Average)
            {
                for (int i = 0; i < LargeMarkCount; i++)
                {
                    dic.Add(i, i * (SweepRange / (LargeMarkCount - 1)));
                }
            }
            else
            {
                for (int i = 0; i < CustomMarkValue.Length; i++)
                {
                    dic.Add(i, (CustomMarkValue[i] - CustomMarkValue.Min()) / Math.Abs((CustomMarkValue.Max() - CustomMarkValue.Min())) * SweepRange);
                }
            }
            //绘制外圆
            if (FirstColorHaveMarkCount > dic.Count)
            {
                FirstColorHaveMarkCount = dic.Count;
            }
            float startAngle = (360 - SweepRange) / 2 + 90;
            //第1段
            g.DrawArc(new Pen(FirstColor, OutCircleWidth), OutGap, OutGap, Dimensions - OutGap * 2, Dimensions - OutGap * 2, startAngle, dic[FirstColorHaveMarkCount - 1]);
            //第2段
            g.DrawArc(new Pen(SecondColor, OutCircleWidth), OutGap, OutGap, Dimensions - OutGap * 2, Dimensions - OutGap * 2, dic[FirstColorHaveMarkCount - 1] + startAngle, dic[dic.Count - 1] - dic[FirstColorHaveMarkCount - 1]);
            //绘制刻度
            //偏移原点
            g.TranslateTransform(Dimensions / 2, Dimensions / 2);
            //旋转角度
            g.RotateTransform(-_sweepRange / 2);
            foreach (var key in dic.Keys)
            {
                RectangleF rec = new RectangleF(-2, -(Dimensions - 2 * OutGap) / 2 - OutGap, 4, OutGap * 2);
                if (key != 0)
                {
                    g.RotateTransform(dic[key] - dic[key - 1]);
                }
                if (key < FirstColorHaveMarkCount)
                {
                    g.FillRectangle(new SolidBrush(FirstColor), rec);
                }
                else
                {
                    g.FillRectangle(new SolidBrush(SecondColor), rec);
                }
            }
            //恢复坐标
            g.ResetTransform();
            //移动原点
            g.TranslateTransform(Dimensions / 2, Dimensions / 2);
            //旋转角度
            //  g.RotateTransform(-_sweepRange / 2);
            //绘制MarkWord
            //  PointF p = new PointF((float)(Dimensions * Math.Cos(230*1.0 / 180 * Math.PI)), (float)(Dimensions * Math.Sin(230*1.0 / 180 * Math.PI)));
            // g.DrawLine(Pens.Black, new PointF(0, 0), p);
            float largeInterval = SweepRange / (LargeMarkCount - 1);
            foreach (var key in dic.Keys)
            {
                //绘制文字
                string markWord;
                if (MarkStyle == MarkType.Average)
                {
                    markWord = Math.Round(StartValue + key * (EndValue - StartValue) / (LargeMarkCount - 1), 1).ToString();
                }
                else
                {
                    markWord = Math.Round(CustomMarkValue[key], 1).ToString();
                }
                float wordRadius = Dimensions / 2 - OutCircleWidth - OutGap - InnerGap;
                double x = wordRadius * Math.Cos((dic[key] + startAngle) / 180 * Math.PI);
                double y = wordRadius * Math.Sin((dic[key] + startAngle) / 180 * Math.PI);
                SizeF size = g.MeasureString(markWord, this.Font);
                PointF wordPoint = new PointF((float)x - size.Width / 2, (float)y - size.Height / 2);
                g.DrawString(markWord, MarkWordFont, new SolidBrush(MarkWordColor), wordPoint);
            }
            if (IsWordShow)
            {
                //绘制底部文字
                string txt = string.Format(WordFormat, ActualValue);
                SizeF wordSize = g.MeasureString(txt, WordFont);
                PointF txtPoint = new PointF(-wordSize.Width / 2, Dimensions / 2 * WordPositionFactor);
                g.DrawString(txt, WordFont, new SolidBrush(WordColor), txtPoint);
            }
            //绘制指针
            //圆心半径
            float circleRadius = Dimensions / 2 * this.PointerPartFactor;
            float pointerLength = circleRadius * 6;
            float trackWidth = pointerLength / 4;
            //绘制指针圆心
            g.FillEllipse(new SolidBrush(FirstColor), -circleRadius, -circleRadius, 2 * circleRadius, 2 * circleRadius);
            float relativeAngle;
            if (ActualValue > EndValue)
            {
                relativeAngle = SweepRange;
            }
            else if (ActualValue < StartValue)
            {
                relativeAngle = 0;
            }
            else
            {
                if (MarkStyle == MarkType.Average)
                {
                    relativeAngle = ((ActualValue - StartValue) / (EndValue - StartValue)) * SweepRange;
                }
                else
                {
                    if (CustomMarkValue.Length < 2)
                    {
                        CustomMarkValue = new float[] { 0, 20, 30 };
                    }
                    relativeAngle = (ActualValue - CustomMarkValue.Min()) / (CustomMarkValue.Max() - CustomMarkValue.Min()) * SweepRange;
                }
            }
            //绘制轨迹
            g.DrawArc(new Pen(FirstColor, trackWidth), -pointerLength + trackWidth / 2, -pointerLength + trackWidth / 2, 2 * pointerLength - trackWidth, 2 * pointerLength - trackWidth, startAngle, relativeAngle);
            //旋转角度
            g.RotateTransform(-_sweepRange / 2);
            //当前值对应的相对角度
            //绘制指针
            g.RotateTransform(relativeAngle);
            g.DrawLine(new Pen(FirstColor, 2), -1, 0, -1, -pointerLength);
        }
    }
    public enum MarkType
    {
        /// <summary>
        /// 平均分配刻度
        /// </summary>
        Average,
        /// <summary>
        /// 自定义刻度值分配
        /// </summary>
        Custom
    }
}

